package net.aiotos.driver;
import com.alibaba.fastjson.JSONObject;
import com.beust.jcommander.ParameterException;
import net.aiotos.sdk.IOTOSysI;
import net.aiotos.common.dto.*;
import net.aiotos.common.util.ArgsParser;
import lombok.extern.slf4j.Slf4j;
import org.yaml.snakeyaml.Yaml;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.lang.reflect.Method;
import java.net.SocketTimeoutException;
import java.util.Map;

/**
 * java SDK 1.8 测试用例
 *
 * @author zws
 * @date 2021.05.06
 * @brief
 */
@Slf4j
public class IotosEngine {
    public final static String CERT_DIR_NAME = "certs";
    public final String runDir;
    public final String certDir;
    private IOTOSys zm;

    public <T> IotosEngine(Class<T> tClass) throws NoSuchMethodException {
        String runDir = getRunDir(tClass);
        this.runDir = runDir;
        log.info("运行目录：{}", this.runDir);
        this.certDir = this.runDir + File.separator + CERT_DIR_NAME;
        log.info("证书目录：{}", this.certDir);
    }

    /**
     *
     * @param runDir 传入运行目录（目录存放certs, cache），读取运行所必需的配置或文件
     */
    public IotosEngine(String runDir) {
        this.runDir = runDir;
        log.info("运行目录：{}", this.runDir);
        this.certDir = this.runDir + File.separator + CERT_DIR_NAME;
        log.info("证书目录：{}", this.certDir);
    }

    /**
     * 判断是不是用jar运行程序
     * @param path 当前运行文件名
     * @return
     */
    private static boolean isJarRun(String path) {
        return path.toLowerCase().endsWith(".jar");
    }


    public static ArgsParser argsParser(String[] args) throws Exception {
        return new ArgsParser().parse(args);
    }

    /**
     *
     * @param tClass 传入的必须是执行入口炎（Main.main）
     * @param <T>
     * @return
     */
    public static <T> String getRunDir(Class<T> tClass) throws NoSuchMethodException {
        Method[] methods = tClass.getMethods();
        boolean hasMain = false;
        for (Method method : methods) {
            if(method.getName().equals("main")) {
                hasMain = true;
                continue;
            }
        }
        if(hasMain == false) {
            throw new NoSuchMethodException(String.format("%s:不存在执行入口main方法", tClass.getName()));
        }
        String currentPath = tClass.getProtectionDomain().getCodeSource().getLocation().getFile();
        String run_dir = null;
        if(isJarRun(currentPath)) {
            String[] paths = currentPath.split("/");
            run_dir = currentPath.replace("/" + paths[paths.length - 1], "");
        } else {
            run_dir = System.getProperty("user.dir");
        }

        return run_dir;

    }


    public IotosYmlConfig.IotosService getArgsParser(String[] args) throws Exception {
        ArgsParser argsParser = null;
        try {
            argsParser = argsParser(args);
            log.info("argsParser:{}", JSONObject.toJSONString(argsParser));
            IotosYmlConfig.IotosService iotosService = new IotosYmlConfig.IotosService();
            iotosService.setHost(argsParser.getHost());
            iotosService.setUsername(argsParser.getUsername());
            iotosService.setPassword(argsParser.getPassword());
            iotosService.setUuid(argsParser.getUuid());
            return iotosService;
        } catch (ParameterException parameterException) {

        }
        File ymlFile = new File(this.runDir + "/iotos.yml");
        if(!(ymlFile.exists() && ymlFile.isFile())) {
            if(argsParser != null) {
                argsParser.getUsage();
            }
            throw new Exception("iotos.yml配置运行配置文件不存在或者请使用命令行参数");
        }
        if(!ymlFile.canRead()) {
            throw new Exception("iotos.yml不可读，请设置文件操作权限");
        }
        FileReader fileReader = new FileReader(ymlFile);
        Reader reader = new BufferedReader(fileReader);


        Yaml yaml = new Yaml();
        JSONObject ymlJson = yaml.loadAs(fileReader, JSONObject.class);
        IotosYmlConfig iotosYmlConfig = new IotosYmlConfig();
        iotosYmlConfig.setVersion(ymlJson.getFloat("version"));
        iotosYmlConfig.setEnv(ymlJson.getString("env"));

        ymlJson.remove("version");
        ymlJson.remove("env");

        IotosYmlConfig.IotosService iotosService = null;
        for (Map.Entry<String, Object> entry : ymlJson.entrySet()) {
            iotosService = ymlJson.getJSONObject(entry.getKey()).toJavaObject(IotosYmlConfig.IotosService.class);
            iotosYmlConfig.getServices().put(entry.getKey(), iotosService);
        }

        log.info("service:{}", iotosYmlConfig);


        if(iotosYmlConfig.getServices().size() != 1) {
            if(iotosYmlConfig.getEnv() != null && iotosYmlConfig.getServices().containsKey(iotosYmlConfig.getEnv())) {
                iotosService = iotosYmlConfig.getServices().get(iotosYmlConfig.getEnv());
            } else if(!iotosYmlConfig.getServices().containsKey("default")) {
                throw new NotImplementedException();
            } else {
                iotosService = iotosYmlConfig.getServices().get("default");
            }
        }
        return iotosService;
    }
    // --u test --p 123456 --h http://192.168.189.128:8000 --i fac4c9c8609211eb834e000c2918bb69
    // -Dorg.slf4j.simpleLogger.defaultLogLevel=trace
    public void engineRun(String[] args) throws Exception {

        //Test
        IotosYmlConfig.IotosService argsParser = getArgsParser(args);
        zm = new IOTOSys(new IOTOSysI(runDir));

        try {
            LoginDTO webLoginParam = new LoginDTO(argsParser.getUsername(), argsParser.getPassword(), argsParser
                    .getUuid(), argsParser.getHost(), certDir);
            webLoginParam.validate();
            ResultDTO t = zm.Login(webLoginParam);
            log.info("登录-->{}", t);
            if(t.getCode() != ErrorEnum.Successfull) {
                throw new Exception(t.getMsg());
            }

            //补全点表信息
            ResultDTO engineInit = engineInit();
            log.info("engineInit => {}", engineInit);

            ResultDTO resultDTO = zm.engineRun();
            if(resultDTO.getCode() != ErrorEnum.NotDriver) {
                while (true) {

                }
            }
        } catch (Ice.SecurityException exception) { // 证书相关异常
            log.error("证书相关异常:{}", exception.reason, exception);
        } catch (SocketTimeoutException exception) {
            log.error("服务器连接失败：{}->{}", exception.getClass().getName(), exception.getMessage(), exception);
        } catch (Exception exception) {
            log.error("未知异常", exception);
        } finally {
            zm.iotoSysI.destroy();
            System.exit(-1);
        }
    }

    public ResultDTO engineInit() throws Exception {
        IonodeDTO ionodeDTO = zm.iotoSysI.getIonodeDTO();
        return zm.engineInit(ionodeDTO);
    }

    public ResultDTO engineStop() {
        return zm.engineStop();
    }


    public static void main(String[] args) throws Exception {
        IotosEngine iotosEngine = new IotosEngine(IotosEngine.class);
        iotosEngine.engineRun(args);
    }


}
